package com.upc.sealback.utils.PublicSeal.repository;

import com.upc.sealback.bean.PublicSeal.SealCircle;
import com.upc.sealback.bean.PublicSeal.SealConfiguration;
import com.upc.sealback.bean.PublicSeal.SealFont;
import com.upc.sealback.utils.ByteUtils;
import com.upc.sealback.utils.FileUtils;
import sun.font.FontDesignMetrics;

import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;

import static com.upc.sealback.utils.FontUtils.SEAL_SAVE_PATH;
import static com.upc.sealback.utils.PublicSeal.TYSeal.buildSeal;
import static com.upc.sealback.utils.FontUtils.Font_SongTi;

/**
 * @description 画圆形/椭圆的样式
 */
public class SealRepository {

    /**
     * 绘制圆弧形文字
     * @param g2d 画笔
     * @param circleRadius 弧形半径
     * @param font 字体对象
     * @param isTop 是否字体在上部，否则在下部
     */
    public static void drawArcFont4Circle(Graphics2D g2d, int circleRadius, SealFont font, boolean isTop) {
        if (font != null) {
            //1.字体长度
            int fontTextLen = font.getFontText().length();
            //2.字体大小，默认根据字体长度动态设定 TODO
            int fontSize = font.getFontSize() == null ? 55 - fontTextLen * 2 : font.getFontSize();
            //3.字体样式
            int fontStyle = font.getIsBold() ? 1 : 0;
            //4.构造字体
            Font f = new Font(font.getFontFamily(), fontStyle, fontSize);

            FontRenderContext context = g2d.getFontRenderContext();
            Rectangle2D rectangle = f.getStringBounds(font.getFontText(), context);
            //5.文字之间间距，默认动态调整
            double fontSpace;
            if (font.getFontSpace() != null) {
                fontSpace = font.getFontSpace();
            } else if (fontTextLen == 1) {
                fontSpace = 0.0D;
            } else {
                fontSpace = rectangle.getWidth() / (double)(fontTextLen - 1) * 0.9D;
            }
            //6.距离外圈距离
            int marginSize = font.getMarginSize() == null ? 10 : font.getMarginSize();
            double newRadius = (double)circleRadius + rectangle.getY() - (double)marginSize;
            double radianPerInterval = 2.0D * Math.asin(fontSpace / (2.0D * newRadius));
            double fix = 0.04D;
            if (isTop) {
                fix = 0.18D;
            }

            double firstAngle;
            if (!isTop) {
                if (fontTextLen % 2 == 1) {
                    firstAngle = 4.71238898038469D - (double)(fontTextLen - 1) * radianPerInterval / 2.0D - fix;
                } else {
                    firstAngle = 4.71238898038469D - ((double)fontTextLen / 2.0D - 0.5D) * radianPerInterval - fix;
                }
            } else if (fontTextLen % 2 == 1) {
                firstAngle = (double)(fontTextLen - 1) * radianPerInterval / 2.0D + 1.5707963267948966D + fix;
            } else {
                firstAngle = ((double)fontTextLen / 2.0D - 0.5D) * radianPerInterval + 1.5707963267948966D + fix;
            }

            for(int i = 0; i < fontTextLen; ++i) {
                double theta;
                double thetaX;
                double thetaY;
                if (!isTop) {
                    theta = firstAngle + (double)i * radianPerInterval;
                    thetaX = newRadius * Math.sin(1.5707963267948966D - theta);
                    thetaY = newRadius * Math.cos(theta - 1.5707963267948966D);
                } else {
                    theta = firstAngle - (double)i * radianPerInterval;
                    thetaX = newRadius * Math.sin(1.5707963267948966D - theta);
                    thetaY = newRadius * Math.cos(theta - 1.5707963267948966D);
                }

                AffineTransform transform;
                if (!isTop) {
                    transform = AffineTransform.getRotateInstance(4.71238898038469D - theta);
                } else {
                    transform = AffineTransform.getRotateInstance(1.5707963267948966D - theta + Math.toRadians(8.0D));
                }

                Font f2 = f.deriveFont(transform);
                g2d.setFont(f2);
                //画字 param1:文字 param2:距离左侧边缘线的距离 param3:距离上边缘线的距离
                g2d.drawString(font.getFontText().substring(i, i + 1), (float)((double)circleRadius + thetaX + 133.0D), (float)((double)circleRadius - thetaY + 135.0D));
            }

        }
    }

    /**
     * 绘制椭圆弧形文字
     *
     * @param g2d 画笔
     * @param circle 外围圆
     * @param font 字体对象
     * @param isTop 是否字体在上部，否则在下部
     */
    public static void drawArcFont4Oval(Graphics2D g2d, SealCircle circle, SealFont font, boolean isTop) {
        if (font != null) {
            float radiusX = (float)circle.getWidth();
            float radiusY = (float)circle.getHeight();
            float radiusWidth = radiusX + (float)circle.getLineSize();
            float radiusHeight = radiusY + (float)circle.getLineSize();
            //1.字体长度
            int fontTextLen = font.getFontText().length();
            //2.字体大小，默认根据字体长度动态设定
            int fontSize = font.getFontSize() == null ? 30 + (10 - fontTextLen) / 2 : font.getFontSize();

            //4.构造字体
            Font f = new Font(Font_SongTi, Font.BOLD, fontSize);

            //5.总的角跨度
            float totalArcAng = 190.0F;
            if (!isTop) {
                totalArcAng = 120.0F;
            }

            //6.从边线向中心的移动因子
            float minRat = 0.7F;
            double startAngle = isTop ? (double)(-90.0F - totalArcAng / 2.0F) : (double)(90.0F - totalArcAng / 2.0F);
            double step = 0.5D;
            int alCount = (int)Math.ceil((double)totalArcAng / step) + 1;
            double[] angleArr = new double[alCount];
            double[] arcLenArr = new double[alCount];
            int num = 0;
            double accArcLen = 0.0D;
            angleArr[num] = startAngle;
            arcLenArr[num] = accArcLen;
            num = num + 1;
            double angR = startAngle * 3.141592653589793D / 180.0D;
            double lastX = (double)radiusX * Math.cos(angR) + (double)radiusWidth;
            double lastY = (double)radiusY * Math.sin(angR) + (double)radiusHeight;

            double arcPer;
            for(arcPer = startAngle + step; num < alCount; arcPer += step) {
                angR = arcPer * 3.141592653589793D / 180.0D;
                double x = (double)radiusX * Math.cos(angR) + (double)radiusWidth;
                double y = (double)radiusY * Math.sin(angR) + (double)radiusHeight;
                accArcLen += Math.sqrt((lastX - x) * (lastX - x) + (lastY - y) * (lastY - y));
                angleArr[num] = arcPer;
                arcLenArr[num] = accArcLen;
                lastX = x;
                lastY = y;
                ++num;
            }

            arcPer = accArcLen / (double)fontTextLen;

            for(int i = 0; i < fontTextLen; ++i) {
                double arcL = (double)i * arcPer + arcPer / 2.0D;
                double ang = 0.0D;

                for(int p = 0; p < arcLenArr.length - 1; ++p) {
                    if (arcLenArr[p] <= arcL && arcL <= arcLenArr[p + 1]) {
                        ang = arcL >= (arcLenArr[p] + arcLenArr[p + 1]) / 2.0D ? angleArr[p + 1] : angleArr[p];
                        break;
                    }
                }

                angR = ang * 3.141592653589793D / 180.0D;
                Float x = radiusX * (float)Math.cos(angR) + radiusWidth;
                Float y = radiusY * (float)Math.sin(angR) + radiusHeight;
                double qxang = Math.atan2((double)radiusY * Math.cos(angR), (double)(-radiusX) * Math.sin(angR));
                double fxang = qxang + 1.5707963267948966D;
                int subIndex = isTop ? i : fontTextLen - 1 - i;
                String c = font.getFontText().substring(subIndex, subIndex + 1);
                //获取文字高宽
                FontMetrics fm = FontDesignMetrics.getMetrics(f);
                int w = fm.stringWidth(c);
                int h = fm.getHeight();
                if (isTop) {
                    x = x + (float)h * minRat * (float)Math.cos(fxang);
                    y = y + (float)h * minRat * (float)Math.sin(fxang);
                    x = x + (float)(-w) / 2.0F * (float)Math.cos(qxang);
                    y = y + (float)(-w) / 2.0F * (float)Math.sin(qxang);
                } else {
                    x = x + (float)h * minRat * (float)Math.cos(fxang);
                    y = y + (float)h * minRat * (float)Math.sin(fxang);
                    x = x + (float)w / 2.0F * (float)Math.cos(qxang);
                    y = y + (float)w / 2.0F * (float)Math.sin(qxang);
                }
                // 旋转
                AffineTransform affineTransform = new AffineTransform();
                affineTransform.scale(0.8D, 1.0D);
                if (isTop) {
                    affineTransform.rotate(Math.toRadians(fxang * 180.0D / 3.141592653589793D - 90.0D), 0.0D, 0.0D);
                } else {
                    affineTransform.rotate(Math.toRadians(fxang * 180.0D / 3.141592653589793D + 180.0D - 90.0D), 0.0D, 0.0D);
                }

                Font f2 = f.deriveFont(affineTransform);
                g2d.setFont(f2);
                g2d.drawString(c, x.intValue() + 107, y.intValue() + 155);
            }

        }
    }


    /**
     * 画横向文字
     *
     * @param g2d 画笔
     * @param circleWidth 边线圆宽度
     * @param circleHeight 边线圆高度
     * @param font 字体对象
     */
    public static void drawFont(Graphics2D g2d, int circleWidth, int circleHeight, SealFont font) {
        if (font != null) {
            //1.字体长度
            int fontTextLen = font.getFontText().length();
            //2.字体大小，默认根据字体长度动态设定
            int fontSize = font.getFontSize() == null ? 55 - fontTextLen * 2 : font.getFontSize();
            //3.字体样式
            int fontStyle = font.getIsBold() ? 1 : 0;
            //4.构造字体
            Font f = new Font(font.getFontFamily(), fontStyle, fontSize);
            g2d.setFont(f);
            FontRenderContext context = g2d.getFontRenderContext();
            String[] fontTexts = font.getFontText().split("\n");
            float marginSize;
            if (fontTexts.length > 1) {
                int y = 0;
                String[] var11 = fontTexts;
                int var12 = fontTexts.length;

                int var13;
                for(var13 = 0; var13 < var12; ++var13) {
                    String fontText = var11[var13];
                    y = (int)((double)y + Math.abs(f.getStringBounds(fontText, context).getHeight()));
                }

                marginSize = 10.0F + (float)(circleHeight / 2 - y / 2);
                String[] var19 = fontTexts;
                var13 = fontTexts.length;

                for(int var20 = 0; var20 < var13; ++var20) {
                    String fontText = var19[var20];
                    Rectangle2D rectangle2D = f.getStringBounds(fontText, context);
                    g2d.drawString(fontText, (float)((double)(circleWidth / 2) - rectangle2D.getCenterX() + 1.0D) , marginSize);
                    marginSize = (float)((double)marginSize + Math.abs(rectangle2D.getHeight()));
                }
            } else {
                Rectangle2D rectangle2D = f.getStringBounds(font.getFontText(), context);
                marginSize = font.getMarginSize() == null ? (float)((double)(circleHeight / 2) - rectangle2D.getCenterY()) : (float)((double)(circleHeight / 2) - rectangle2D.getCenterY()) + (float)font.getMarginSize();
                g2d.drawString(font.getFontText(), (float)((double)(circleWidth / 2) - rectangle2D.getCenterX() + 1.0D) + 125, marginSize+125);
            }

        }
    }

    /**
     * 画横向文字 —— 发票专用章
     *
     * @param g2d 画笔
     * @param circleWidth 边线圆宽度
     * @param circleHeight 边线圆高度
     * @param font 字体对象
     */
    public static void drawNumFont(Graphics2D g2d, int circleWidth, int circleHeight, SealFont font) {
        if (font != null) {
            //1.字体长度
            int fontTextLen = font.getFontText().length();
            //2.字体大小，默认根据字体长度动态设定
            int fontSize = 24;
            //3.字体样式
            int fontStyle = font.getIsBold() ? 1 : 0;
            //4.构造字体
            Font f = new Font(font.getFontFamily(), fontStyle, fontSize);
            g2d.setFont(f);
            FontRenderContext context = g2d.getFontRenderContext();
            String[] fontTexts = font.getFontText().split("\n");
            float marginSize;
            if (fontTexts.length > 1) {
                int y = 0;
                String[] var11 = fontTexts;
                int var12 = fontTexts.length;

                int var13;
                for(var13 = 0; var13 < var12; ++var13) {
                    String fontText = var11[var13];
                    y = (int)((double)y + Math.abs(f.getStringBounds(fontText, context).getHeight()));
                }

                marginSize = 10.0F + (float)(circleHeight / 2 - y / 2);
                String[] var19 = fontTexts;
                var13 = fontTexts.length;

                for(int var20 = 0; var20 < var13; ++var20) {
                    String fontText = var19[var20];
                    Rectangle2D rectangle2D = f.getStringBounds(fontText, context);
                    g2d.drawString(fontText, (float)((double)(circleWidth / 2) - rectangle2D.getCenterX() + 1.0D), marginSize);
                    marginSize = (float)((double)marginSize + Math.abs(rectangle2D.getHeight()));
                }
            }
            else {
                Rectangle2D rectangle2D = f.getStringBounds(font.getFontText(), context);
                marginSize = font.getMarginSize() == null ? (float)((double)(circleHeight / 2) - rectangle2D.getCenterY()) : (float)((double)(circleHeight / 2) - rectangle2D.getCenterY()) + (float)font.getMarginSize();
                g2d.drawString(font.getFontText(), (float)((double)(circleWidth / 2) - rectangle2D.getCenterX() + 1.0D), marginSize);
            }

        }
    }

    /**
     * 画圆
     *
     * @param g2d 画笔
     * @param circle 圆配置对象
     */
    public static void drawCircle(Graphics2D g2d, SealCircle circle, int x, int y) {
        if (circle != null) {
            //1.圆线条粗细默认是圆直径的2/35
            int lineSize = circle.getLineSize() == null ? circle.getHeight() * 2 / 34 : circle.getLineSize();
            //2.画圆
            g2d.setStroke(new BasicStroke((float)lineSize));
            g2d.drawOval(x+125, y+125, circle.getWidth() * 2, circle.getHeight() * 2);
        }
    }


    /**
     * 具体处理方法
     * @param configuration
     * @return
     * @throws Exception
     */
    public static String dealWith(SealConfiguration configuration) throws Exception {
        BufferedImage bi = buildSeal(configuration);
        byte[] bs = ByteUtils.buildBytes(bi);
        String fullPath = ByteUtils.storeBytes(bs,SEAL_SAVE_PATH);
        String base64 = FileUtils.fileToBase64(new File(fullPath));
        return base64;
    }

    /**
     * 具体处理方法-存储到本地
     * @param configuration
     * @return
     * @throws Exception
     */
    public static String dealWithLocal(SealConfiguration configuration) throws Exception {
        BufferedImage bi = buildSeal(configuration);
        byte[] bs = ByteUtils.buildBytes(bi);
        String fullPath = ByteUtils.storeBytes(bs,SEAL_SAVE_PATH);
        return fullPath;
    }

}
